from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
import json
import hashlib


class SystemBackup(models.Model):
    """系统备份模型"""
    
    BACKUP_TYPES = [
        ('menu_operation', '菜单操作备份'),
        ('system_snapshot', '系统快照备份'),
        ('emergency', '紧急备份'),
        ('manual', '手动备份'),
        ('auto', '自动备份'),
    ]
    
    STATUS_CHOICES = [
        ('creating', '创建中'),
        ('completed', '已完成'),
        ('failed', '失败'),
        ('corrupted', '已损坏'),
    ]

    id = models.AutoField(primary_key=True)
    backup_type = models.CharField(max_length=20, choices=BACKUP_TYPES, default='manual')
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='creating')
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    completed_at = models.DateTimeField(null=True, blank=True)
    description = models.TextField(default='')

    # 备份数据
    menu_data = models.JSONField(default=dict, help_text='菜单数据备份')
    permission_data = models.JSONField(default=dict, help_text='权限数据备份')
    file_data = models.JSONField(default=dict, help_text='文件数据备份')
    config_data = models.JSONField(default=dict, help_text='配置数据备份')

    # 备份元数据
    checksum = models.CharField(max_length=64, default='', help_text='数据校验和')
    size_bytes = models.BigIntegerField(default=0, help_text='备份大小(字节)')
    is_valid = models.BooleanField(default=True, help_text='备份是否有效')
    
    # 备份文件路径
    backup_file_path = models.CharField(max_length=500, default='', help_text='备份文件路径')
    
    # 恢复相关
    restore_count = models.IntegerField(default=0, help_text='恢复次数')
    last_restored_at = models.DateTimeField(null=True, blank=True, help_text='最后恢复时间')
    last_restored_by = models.ForeignKey(
        User, 
        on_delete=models.SET_NULL, 
        null=True, 
        blank=True,
        related_name='restored_backups',
        help_text='最后恢复人'
    )

    class Meta:
        db_table = 'system_backup'
        ordering = ['-created_at']
        verbose_name = '系统备份'
        verbose_name_plural = '系统备份'
        indexes = [
            models.Index(fields=['backup_type', 'status']),
            models.Index(fields=['created_at']),
            models.Index(fields=['is_valid']),
        ]

    def __str__(self):
        return f"{self.get_backup_type_display()} - {self.created_at.strftime('%Y-%m-%d %H:%M:%S')}"

    def save(self, *args, **kwargs):
        # 自动计算校验和
        if self.menu_data or self.permission_data or self.file_data or self.config_data:
            self.checksum = self.calculate_checksum()
        
        # 设置完成时间
        if self.status == 'completed' and not self.completed_at:
            self.completed_at = timezone.now()
            
        super().save(*args, **kwargs)

    def calculate_checksum(self):
        """计算备份数据的校验和"""
        data_str = json.dumps({
            'menu_data': self.menu_data,
            'permission_data': self.permission_data,
            'file_data': self.file_data,
            'config_data': self.config_data
        }, sort_keys=True)
        return hashlib.sha256(data_str.encode()).hexdigest()

    def validate_integrity(self):
        """验证备份完整性"""
        if not self.checksum:
            return False
        
        current_checksum = self.calculate_checksum()
        return current_checksum == self.checksum

    def get_backup_size_display(self):
        """获取备份大小的友好显示"""
        if self.size_bytes < 1024:
            return f"{self.size_bytes} B"
        elif self.size_bytes < 1024 * 1024:
            return f"{self.size_bytes / 1024:.1f} KB"
        elif self.size_bytes < 1024 * 1024 * 1024:
            return f"{self.size_bytes / (1024 * 1024):.1f} MB"
        else:
            return f"{self.size_bytes / (1024 * 1024 * 1024):.1f} GB"

    def mark_as_restored(self, user=None):
        """标记为已恢复"""
        self.restore_count += 1
        self.last_restored_at = timezone.now()
        if user:
            self.last_restored_by = user
        self.save(update_fields=['restore_count', 'last_restored_at', 'last_restored_by'])

    @classmethod
    def get_recent_backups(cls, days=30, limit=10):
        """获取最近的备份"""
        cutoff_date = timezone.now() - timezone.timedelta(days=days)
        return cls.objects.filter(
            created_at__gte=cutoff_date,
            is_valid=True
        ).order_by('-created_at')[:limit]

    @classmethod
    def cleanup_old_backups(cls, keep_days=90):
        """清理旧备份"""
        cutoff_date = timezone.now() - timezone.timedelta(days=keep_days)
        old_backups = cls.objects.filter(created_at__lt=cutoff_date)
        
        deleted_count = 0
        for backup in old_backups:
            # 删除备份文件
            if backup.backup_file_path:
                try:
                    import os
                    if os.path.exists(backup.backup_file_path):
                        os.remove(backup.backup_file_path)
                except Exception:
                    pass
            
            backup.delete()
            deleted_count += 1
        
        return deleted_count


class BackupOperation(models.Model):
    """备份操作记录"""
    
    OPERATION_TYPES = [
        ('create', '创建备份'),
        ('restore', '恢复备份'),
        ('delete', '删除备份'),
        ('validate', '验证备份'),
    ]
    
    STATUS_CHOICES = [
        ('pending', '等待中'),
        ('running', '执行中'),
        ('success', '成功'),
        ('failed', '失败'),
    ]

    id = models.AutoField(primary_key=True)
    backup = models.ForeignKey(SystemBackup, on_delete=models.CASCADE, related_name='operations')
    operation_type = models.CharField(max_length=20, choices=OPERATION_TYPES)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
    
    started_at = models.DateTimeField(auto_now_add=True)
    completed_at = models.DateTimeField(null=True, blank=True)
    
    operated_by = models.ForeignKey(User, on_delete=models.CASCADE)
    
    # 操作详情
    operation_data = models.JSONField(default=dict, help_text='操作相关数据')
    result_data = models.JSONField(default=dict, help_text='操作结果数据')
    error_message = models.TextField(default='', help_text='错误信息')
    
    # 性能指标
    duration_seconds = models.FloatField(null=True, blank=True, help_text='操作耗时(秒)')
    processed_items = models.IntegerField(default=0, help_text='处理项目数')

    class Meta:
        db_table = 'backup_operation'
        ordering = ['-started_at']
        verbose_name = '备份操作'
        verbose_name_plural = '备份操作'

    def __str__(self):
        return f"{self.get_operation_type_display()} - {self.backup}"

    def mark_as_completed(self, success=True, result_data=None, error_message=''):
        """标记操作完成"""
        self.completed_at = timezone.now()
        self.status = 'success' if success else 'failed'
        
        if result_data:
            self.result_data = result_data
        
        if error_message:
            self.error_message = error_message
        
        # 计算耗时
        if self.started_at and self.completed_at:
            duration = self.completed_at - self.started_at
            self.duration_seconds = duration.total_seconds()
        
        self.save()

    @property
    def is_completed(self):
        """是否已完成"""
        return self.status in ['success', 'failed']

    @property
    def is_successful(self):
        """是否成功"""
        return self.status == 'success'
